package heliotrope.net.loader
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	
	import heliotrope.res.ResourceMission;

	[Event(name="complete",type="flash.events.Event")]
	[Event(name="progress",type="flash.events.ProgressEvent")]
	[Event(name="ioError",  type="flash.events.IOErrorEvent")]
	
	public class QueueLoader extends EventDispatcher
	{		
		private var _loaders:Array;
		private var _loadQueue:Array;
		private var _freeLoaders:Array;
		private var _loaderNum:int;
//		private var _missionId:uint = 0;
		private var _totalMission:Number;
		private var _finishedMission:Number;
		private var _globalRetryTimes:uint;
		public function QueueLoader(loaderNum_:int = 4, retryTimes_:uint = 0)
		{
			if(loaderNum_<=0) throw new ArgumentError("Number of loader should >0");
			_loaderNum	= loaderNum_;
			_loaders	= new Array(_loaderNum);
			_loadQueue	= [];
			_freeLoaders	= [];
			_totalMission	= 0;
			_finishedMission= 0;
			_globalRetryTimes = retryTimes_;
			for(var i:int=0; i<_loaderNum; i++)
			{
				_freeLoaders[i] = _loaders[i] = new CommonLoader(i);
			}
		}
		
		public function addMission(mission_:LoadMission):void
		{
			_totalMission++;
			if(mission_.retry == -1) mission_.retry = _globalRetryTimes;
			var loader:CommonLoader = _freeLoaders.pop();
 			if(loader)
			{
				loader.addEventListener(Event.COMPLETE, completeHandler);
				loader.addEventListener(IOErrorEvent.IO_ERROR, errorHandler);
				loader.addEventListener(ProgressEvent.PROGRESS, progressHandler);
				handleHost(mission_, LoadState.LOADING);
				loader.load(mission_);
			} 
			else
			{
				_loadQueue.push(mission_);
				handleHost(mission_, LoadState.IN_QUEUE);
			}
		}
		
		protected function progressHandler(event_:ProgressEvent):void
		{
			var mission:LoadMission = (event_.target as CommonLoader).currentMission;
			mission.dispatchEvent(event_);
		}
		
		protected function completeHandler(event_:Event):void
		{
			var loader:CommonLoader = event_.target as CommonLoader;
			loader.currentMission.dispatchEvent(new Event(Event.COMPLETE));
			dispatchEvent(new ProgressEvent(ProgressEvent.PROGRESS, false, false, _finishedMission, _totalMission));
			_finishedMission++;
			var mission:LoadMission = _loadQueue.shift();
			if(mission)
			{
				handleHost(mission, LoadState.LOADING);
				loader.load(mission);
			}
			else
			{
				loader.removeEventListener(Event.COMPLETE, completeHandler);
				loader.removeEventListener(IOErrorEvent.IO_ERROR, errorHandler);
				loader.removeEventListener(ProgressEvent.PROGRESS, progressHandler);
				_freeLoaders.push(loader);
				dispatchEvent(new Event(Event.COMPLETE));
				_totalMission = _finishedMission = 0;
			}
		}
		
		protected function errorHandler(event:Event):void
		{
			var loader:CommonLoader = event.target as CommonLoader;
			var errorMission:LoadMission = loader.currentMission;
			handleHost(errorMission, LoadState.NOT_LOAD);
			dispatchEvent(event);
			
			var mission:LoadMission;	
			mission = _loadQueue.shift();
			if(mission)
			{
				handleHost(mission, LoadState.LOADING);
				loader.load(mission);
			}
			else
			{
				loader.removeEventListener(Event.COMPLETE, completeHandler);
				loader.removeEventListener(IOErrorEvent.IO_ERROR, errorHandler);
				_freeLoaders.push(loader);
			}
		}
		
		private function handleHost(mission_:LoadMission, state_:String):Boolean
		{
			if(mission_ is ResourceMission)
			{
				var temp:ResourceMission = mission_ as ResourceMission;
				temp.host.setLoadState(new LoadState(mission_.target as IStateTarget, state_));
				return true;
			}
			return false;
		}
		
//		public function getId():uint
//		{
//			return _missionId++;
//		}

//		public function getCurrentMissionCompleteEvent():String
//		{
//			return Event.COMPLETE+obj_id+_missionId;
//		}
//		public function getCurrentMissionProgressEvent():String
//		{
//			return ProgressEvent.PROGRESS+obj_id+_missionId;
//		}
	}
}
